
const canvas = document.getElementById('gameUI');
const context = canvas.getContext('2d');
const images = {};
const list=['../image/tex1.jpg','../image/tex2.jpg','../image/tex3.jpg','../image/tex4.jpg'];   //添加需要使用到的材质图片路径


//加载绘制图片
function getImageUrl(url)
{
    return images[url];
}

//加载一张图片
function loadImage(url,callback)
{
    const image= new Image();
    image.src=url;
    image.onload=function()
    {   
        images[url]=image;
        callback();
    }

}

//加载多张图片
function loadMultiImage(list, onSuccess)
{
    let current=0;
    const total=list.length;
    for(const item of list)
    {
    loadImage(item,function(){
        current++;
         if(current === total)
          {
            onSuccess();
          }
        })
    }
}

class AbstractRenderer {
    /**
     * 父节点
     */
    parent = null
    /**
     * x缩放
     */
    scaleX = 1;
    /**
     * 
     * y缩放
     */
    scaleY = 1;
    /**
     * 旋转
     */
    rotation = 0;
    /**
     * x平移
     */
    x = 0;
    /**
     * y平移
     */
    y = 0;


    /**
     * 是否可见
     */
    visible = true;

    /**
     * 透明度
     */
    alpha = 1;

    /**
     * 全局透明度
     */
    $globalAlpha = 1;

    /**
     * 相对矩阵
     */
    $localMatrix;

    /**
     * 绝对矩阵
     */
    $globalMatrix;

    /*移动方向 0为左右，1为上下*/
    movedirection ;

    /*回头标志符*/
    isback ;

    /*移动的下限和上限*/
    range = [] ;
    
    /*移动速度*/
    speed;
    
    constructor() {
        this.$localMatrix = new Matrix();
        this.$globalMatrix = new Matrix();
    }

    calculateGlobalProperties() {
        this.$localMatrix.updateFromDisplayObject(this.x, this.y, this.scaleX, this.scaleY, this.rotation);
        this.$globalMatrix = matrixAppendMatrix(this.$localMatrix, this.parent.$globalMatrix);
        this.$globalAlpha = this.parent.$globalAlpha * this.alpha;
    }


    //提供可重写的渲染函数接口
    draw(context) {
        this.calculateGlobalProperties();

        context.setTransform(
            this.$globalMatrix.a,
            this.$globalMatrix.b,
            this.$globalMatrix.c,
            this.$globalMatrix.d,
            this.$globalMatrix.tx,
            this.$globalMatrix.ty
        )
        context.globalAlpha = this.$globalAlpha;

        if (this.visible) 
        {
            this.render(context);
        }
    }
    
    render(context) {}
    
    move()  {}

    hitTest(point)  {}
}


class DisplayObjectContainer extends AbstractRenderer {

    children = [];

    addChild(child) {
        const index = this.children.indexOf(child);
        child.parent = this;
        if (index == -1) {
            this.children.push(child);
        }
    }

    removeChild(child) {
        const index = this.children.indexOf(child);
        child.parent = null;
        if (index >= 0) {
            this.children.splice(index, 1);
        }
    }

    render(context) {
        for (let child of this.children) {
            child.draw(context);
        }
    }

    hitTest(point) {
        for (let i = this.children.length - 1; i >= 0; i--) {
            const child = this.children[i];
            const localMatrix = child.$localMatrix;
            const invertLocalMatrix = invertMatrix(localMatrix);
            //相对于子对象的相对坐标 = 相对于当前对象的相对坐标 * 子对象的相对矩阵的逆矩阵
            const childLocalPoint = pointAppendMatrix(point, invertLocalMatrix);
            const result = child.hitTest(childLocalPoint);
            if (result) {
                return result;
            }
        }
        return null;
    }
}

class RootContainer extends DisplayObjectContainer {

    calculateGlobalProperties() {

    }
}



//绘制背景
class drawBackGoound extends AbstractRenderer 
{   
    color="black";
    render(context){
    context.fillStyle=this.color;
    context.fillRect(0,0,400,400);
    }
}

//绘制其他
class drawOther extends AbstractRenderer
{
    render(context)
   {
    //绘制所有豆子
    drawAllBeans(2.2,"pink",15);

    //绘制外边界
    drawBorder();

    //绘制中心圆角矩形
    drawMRR(200,200,80,60,'blue','white');

    //绘制图片裁剪区域
    //drawClip();
   }
}

//绘制圆角矩形
class drawRR extends AbstractRenderer
{   
    x=0;
    y=0;
    w=0;
    l=0;
    color=null;
    render(context)
    {
    context.strokeStyle=this.color;
    context.lineWidth=2;
    baseRect(0,0,this.w,this.l);
    context.stroke();
    }
}

//绘制下T型地形
class  drawDT extends AbstractRenderer
{   
    x=0;
    y=0;
    color=null;
    render(context)
    {context.strokeStyle=this.color;
    context.lineWidth=2;
    baseDT(0,0);
    context.stroke();}
}

//绘制上T型地形
class drawUT extends AbstractRenderer
    {  
    x=0;
    y=0;
    color=null;
    render(context){
    let Halfw=30;
    let Halfl=0;
    context.strokeStyle=this.color;
    context.lineWidth=2;
    context.beginPath();
    context.moveTo(-Halfw,-10);
    context.lineTo(-20,-10);
    drawRC(-20,-20,4,1);
    context.lineTo(-10,-40);
    drawRC(0,-40,1,0);
    drawRC(0,-40,2,0);
    context.lineTo(10,-20);
    drawRC(20,-20,3,1);
    context.lineTo(+Halfw,-10);
    drawRC(Halfw,-Halfl,2,0);
    drawRC(Halfw,Halfl,4,0);
    context.lineTo(20,Halfl+10);
    context.lineTo(-Halfw,10);
    drawRC(-Halfw,0,3,0);
    drawRC(-Halfw,0,1,0); 
    context.stroke();
    }
}

//绘制右T型地形
class drawRT extends AbstractRenderer
{
    x=0;
    y=0;
    color=null;
    render(context){
    context.strokeStyle=this.color;
    context.lineWidth=2;
    baseRT(0,0);
    context.stroke();
    }
}

//绘制左T型地形
class drawLT extends AbstractRenderer
{
    x=0;
    y=0;
    color=null;
    render(context){
    context.strokeStyle=this.color;
    context.lineWidth=2;
    baseLT(0,0);
    context.stroke();}
}


//绘制右凹形
class drawRConcave extends AbstractRenderer
{   
    x=0;
    y=0;
    color=null;
    render(context){
    let Halfl=30;
    let Halfw=30;
    context.strokeStyle=this.color;
    context.lineWidth=2;
    context.beginPath();
    context.moveTo(-10,Halfl+10);
    context.lineTo(-10,-Halfl);
    drawRC(0,-Halfl,1,0);
    context.lineTo(Halfw+10,-Halfl-10);
    drawRC(Halfw+10,-Halfl,2,0);
    drawRC(Halfw+10,-Halfl,4,0);
    context.lineTo(+20,-Halfl+10);
    drawRC(20,-Halfl+20,1,1);
    context.lineTo(10,Halfl-10);
    drawRC(20,Halfl-10,3,1);
    context.lineTo(Halfw+5,Halfl);
    drawRC(Halfw+5,Halfl+10,2,0);
    drawRC(Halfw+5,Halfl+10,4,0);
    context.lineTo(0,Halfl+20);
    drawRC(0,Halfl+10,3,0);
    context.stroke();}

}

//绘制左凹形
class drawLConcave extends AbstractRenderer
{  
    x=0;
    y=0;
    color=null;
    render(context){
    let Halfl=30;
    let Halfw=30;
    context.strokeStyle=this.color;
    context.lineWidth=2;
    context.beginPath();
    context.moveTo(10,Halfl+10);
    context.lineTo(10,-Halfl);
    drawRC(0,-Halfl,2,1);
    context.lineTo(-Halfw-10,-Halfl-10);
    drawRC(-Halfw-10,-Halfl,1,1);
    drawRC(-Halfw-10,-Halfl,3,1);
    context.lineTo(-20,-Halfl+10);
    drawRC(-20,-Halfl+20,2,0);
    context.lineTo(-10,Halfl-10);
    drawRC(-20,Halfl-10,4,0);
    context.lineTo(-Halfw-5,Halfl);
    drawRC(-Halfw-5,Halfl+10,1,1);
    drawRC(-Halfw-5,Halfl+10,3,1);
    context.lineTo(0,Halfl+20);
    drawRC(0,Halfl+10,4,1);
    context.stroke();
    }
}

//绘制右直角型
class drawRTR extends AbstractRenderer
{   
    x=0;
    y=0;
    color=null;
    render(context){
    let Halfl=20;
    let Halfw=30;
    context.strokeStyle=this.color;
    context.lineWidth=2;
    context.beginPath();
    context.moveTo(10,-Halfl);
    context.lineTo(10,Halfl);
    drawRC(0,Halfl,4,0);
    drawRC(0,Halfl,3,0);
    context.lineTo(-10,-Halfl+20);
    drawRC(-20,-Halfl+20,2,1);
    context.lineTo(-Halfw,-Halfl+10);
    drawRC(-Halfw,-Halfl,3,0);
    drawRC(-Halfw,-Halfl,1,0);
    context.lineTo(0,-Halfl-10);
    drawRC(0,-Halfw+10,2,0);
    context.stroke();
    }

}

//绘制左直角型
class drawLTR extends AbstractRenderer
{   
    x=0;
    y=0;
    color=null;
    render(context){
    let Halfl=20;
    let Halfw=30;
    context.strokeStyle=this.color;
    context.lineWidth=2;
    context.beginPath();
    context.moveTo(-10,-Halfl);
    context.lineTo(-10,Halfl);
    drawRC(0,Halfl,3,1);
    drawRC(0,Halfl,4,1);
    context.lineTo(10,-Halfl+20);
    drawRC(20,-Halfl+20,1,0);
    context.lineTo(Halfw,-Halfl+10);
    drawRC(Halfw,-Halfl,4,1);
    drawRC(Halfw,-Halfl,2,1);
    context.lineTo(0,-Halfl-10);
    drawRC(0,-Halfw+10,1,1);
    context.stroke();
    }

}

//绘制吃豆人
class drawPlayer extends AbstractRenderer
{ 
   x=0;
   y=0;
   color=null;
   render(context){ 
   context.beginPath();
   let startAngle = (Math.PI/180)*330; // 开始点
   let endAngle = (Math.PI/180)*30;  //结束点
   context.arc(0,0,7,startAngle,endAngle,true); //false是顺时针clockwise绘制，true是逆时针anticlockwise绘制。
   context.lineTo(-5,0);
   context.fillStyle=this.color;
   context.fill();
   }

   hitTest(point) {
    const rectangle = { x: 0, y: 0, width: 20, height: 20 };
    const result = checkPointInRectangle(point, rectangle);
    
    if (result) {
        console.log(`Success!`)
        this.parent.x += 1;
        return this;   
        /*let a=this.parent;
        while(a.parent)
        {
           a =a.parent;
           console.log(1);
        }
        a.x += 1;*/
    }
    else {
        console.log(`Error!`)
        return null;
    }
}
}

//绘制小怪物
class  drawImp extends AbstractRenderer
{   
    x=0;
    y=0;
    righteye=0;
    lefteye=0;
    color=null;

    //绘制身体
    render(context){
    context.fillStyle = this.color;
    context.beginPath();
    context.moveTo(-10,10);
    context.lineTo(-10,0);
    context.arc(0,0,10,Math.PI,0,false);
    context.lineTo(10,10);
    context.lineTo(6.66,12);
    context.lineTo(3.33,10);
    context.lineTo(0,12);
    context.lineTo(-3.33,10);
    context.lineTo(-6.66,12);
    context.lineTo(-10,10);
    context.fill();
     //context.bezierCurveTo(83,94,89,88,97,88);      //贝塞尔曲线，分二次曲线quadraticCurveTo()和三次曲线bezierCurveTo()，1个控制点和1个结束点，2个控制点和1个结束点，起始点为上次操作的延续位置。
   
     //绘制眼白
    context.fillStyle = "white";
    context.beginPath();
    context.arc(4.5,0,4,0,Math.PI*2,true);
    context.fill();
    context.beginPath();
    context.arc(-4.5,0,4,0,Math.PI*2,true);
    context.fill(); 

    //绘制眼珠
    context.fillStyle = "black";
    context.beginPath();
    context.arc(this.righteye,1.5,1.8,0,Math.PI*2,true); //右眼珠
    context.fill();
    context.beginPath();
    context.arc(this.lefteye,1.5,1.8,0,Math.PI*2,true);  //左眼珠
    context.fill(); 
    }

    move()
    {
    if (this.movedirection === 1)
    {if ( this.isback === false )
       { this.y += this.speed;
        if(this.y >=this.range[1])
        this.isback = true;
        }
     else 
     {  this.y -= this.speed;
        if(this.y <=this.range[0])
        this.isback = false;
    }
    }
   else if (this.movedirection === 0)
    {if ( this.isback === false )
        { this.x += this.speed;
         if(this.x >=this.range[1])
         this.isback = true;
         }
      else 
      {  this.x -= this.speed;
         if(this.x <=this.range[0])
         this.isback = false;
     }
    }
    }
}

//绘制图片
class ImageRenderer extends AbstractRenderer {
    
    x=0;
    y=0;
    w=0;
    l=0;
    image = null;
    
    //重写接口函数
    render(context) {
        if (this.image) {
            context.drawImage(this.image, 0, 0, this.w, this.l);
        }

    }
}


class drawText extends AbstractRenderer {
    
    //初始值
    x=0;
    y=0;
    color = 'black';
    text = 'helloworld';

    render(context) {
        context.font="bold 18px serif"   //注意在字符串中应用变量的格式，不要漏了加号
        context.fillStyle = this.color;
        context.fillText(this.text, 0,0);
    }

}


//引擎核心
class GameEngineCore {

    onStart;

    onUpdate;

    root;
  
    cxt;

    //renderList = [];

    lastIterationTime = 0;

    lastAdvancedTime = 0;
  
    fps = 60;
    

    start() {
        this.root = new RootContainer();
        this.cxt = context;
        
        if(this.cxt)          
           console.log(this.cxt);
    
        else  console.log(`error!`);

        loadMultiImage(['../image/tex1.jpg', '../image/tex2.jpg', '../image/tex3.jpg', '../image/tex4.jpg'], this.onStart)
        requestAnimationFrame(this.onFrame.bind(this));
    }

    saveCanvas(){
        this.cxt.save();
     }
 
     restoreCanvas(){
         this.cxt.restore();
     }
 
     hitTest(point) {
        let result = this.root.hitTest(point);
        while (result) {
            if (result.onClick) {
                result.onClick();
            }
            result = result.parent;
        }
    }

    onFrame(advancedTime) {
        context.save();
        context.clearRect(0, 0, 400, 400)

        const duringTime = advancedTime - this.lastAdvancedTime;
        this.lastAdvancedTime = advancedTime;
        this.lastIterationTime += duringTime;
        const frameTime = 1000 / this.fps;
        
        while (this.lastIterationTime >= frameTime) {
            this.lastIterationTime -= frameTime;
            this.onUpdate(advancedTime);
        }
         
        /*
        //执行每个绘制对象中的draw方法，对渲染列表中的对象进行绘制
        for (let item of this.renderList) {
            item.draw(context);
        }
        */
        this.root.draw(context);
        context.restore();
        requestAnimationFrame(this.onFrame.bind(this));
    }

}


window.addEventListener('click', function (e) {
    const mouseGlobalX = e.offsetX;
    const mouseGlobalY = e.offsetY;
    const point = { x: mouseGlobalX, y: mouseGlobalY };
    core.hitTest(point);
 
})



